import {
  type BoundingBox,
  GraphicObject,
  GraphicType,
  type Point,
  type ViewTransform,
} from '../GraphicObject';
import TransformManager from '../TransformManager';
import type { GraphicObjectData } from '../types';

export class Line extends GraphicObject {
  public start: Point;
  public end: Point;
  static create: (
    start: Point,
    end: Point,
    options?: {
      transform?: any;
      style?: any;
      layerId?: string;
    },
  ) => Line;

  constructor(
    start: Point,
    end: Point,
    transform = GraphicObject.defaultTransform(),
    style = GraphicObject.defaultStyle(),
    layerId = 'default',
  ) {
    super(GraphicType.LINE, transform, style, layerId);
    this.start = { ...start };
    this.end = { ...end };
  }

  draw(ctx: CanvasRenderingContext2D, viewTransform: ViewTransform): void {
    ctx.save();

    // 应用视图变换
    ctx.translate(viewTransform.offset.x, viewTransform.offset.y);
    ctx.scale(viewTransform.scale, viewTransform.scale);
    ctx.rotate(viewTransform.rotation);

    // 应用对象变换
    ctx.translate(this.transform.position.x, this.transform.position.y);
    ctx.rotate(this.transform.rotation);
    ctx.scale(this.transform.scale.x, this.transform.scale.y);

    // 设置样式
    if (this.style.strokeColor) {
      ctx.strokeStyle = this.style.strokeColor;
    }
    if (this.style.strokeWidth) {
      ctx.lineWidth = this.style.strokeWidth / viewTransform.scale;
    }
    if (this.style.opacity) {
      ctx.globalAlpha = this.style.opacity;
    }
    if (this.style.lineDash) {
      ctx.setLineDash(this.style.lineDash);
    }

    // 绘制线条
    ctx.beginPath();
    ctx.moveTo(this.start.x, this.start.y);
    ctx.lineTo(this.end.x, this.end.y);

    if (this.style.strokeColor && this.style.strokeWidth) {
      ctx.stroke();
    }

    ctx.restore();
  }

  contains(point: Point): boolean {
    // 将世界坐标转换为对象局部坐标
    const localPoint = TransformManager.worldToLocal(point, this.transform);

    // 计算点到线段的距离
    const distance = this.distanceToSegment(localPoint, this.start, this.end);
    const tolerance = 5; // 5像素容差

    return distance <= tolerance;
  }

  getBoundingBox(): BoundingBox {
    const minX = Math.min(this.start.x, this.end.x);
    const maxX = Math.max(this.start.x, this.end.x);
    const minY = Math.min(this.start.y, this.end.y);
    const maxY = Math.max(this.start.y, this.end.y);

    return {
      x: this.transform.position.x + minX,
      y: this.transform.position.y + minY,
      width: (maxX - minX) * this.transform.scale.x,
      height: (maxY - minY) * this.transform.scale.y,
    };
  }

  /**
   * 序列化对象数据
   */
  serialize(): GraphicObjectData {
    return {
      id: this.id,
      type: this.type,
      transform: { ...this.transform },
      style: { ...this.style },
      layerId: this.layerId,
      start: { ...this.start },
      end: { ...this.end },
    };
  }

  // 计算点到线段的距离
  private distanceToSegment(point: Point, p1: Point, p2: Point): number {
    const A = point.x - p1.x;
    const B = point.y - p1.y;
    const C = p2.x - p1.x;
    const D = p2.y - p1.y;

    const dot = A * C + B * D;
    const lenSq = C * C + D * D;
    let param = -1;

    if (lenSq !== 0) param = dot / lenSq;

    let xx: number, yy: number;

    if (param < 0) {
      xx = p1.x;
      yy = p1.y;
    } else if (param > 1) {
      xx = p2.x;
      yy = p2.y;
    } else {
      xx = p1.x + param * C;
      yy = p1.y + param * D;
    }

    const dx = point.x - xx;
    const dy = point.y - yy;
    return Math.sqrt(dx * dx + dy * dy);
  }
}

// 静态创建方法
Line.create = (
  start: Point,
  end: Point,
  options?: {
    transform?: any;
    style?: any;
    layerId?: string;
  },
) => {
  return new Line(
    start,
    end,
    options?.transform,
    options?.style,
    options?.layerId,
  );
};
